package com.netx.generics.translation;

import com.netx.generics.basic.Checker;


public class Token extends Position {

	// TYPE:
	public static final int KEYWORD = 1;
	public static final int IDENTIFIER = 2;
	public static final int SEPARATOR = 3;
	public static final int OPERATOR = 4;
	public static final int STRING_CONSTANT = 5;
	public static final int INTEGER_CONSTANT = 6;
	public static final int FLOAT_CONSTANT = 7;
	public static final int CHAR_CONSTANT = 8;

	private final static String[] _names = {
		"KEYWORD", "IDENTIFIER", "SEPARATOR", "OPERATOR", "STRING_CONSTANT",
		"INTEGER_CONSTANT", "FLOAT_CONSTANT", "CHAR_CONSTANT"
	};
	
	public static final String _escapes = "nrtbf0\\";
	
	public static String getEscapeChars() {
		return _escapes;
	}

	// INSTANCE:
	private final int _type;
	private final int _length;
	private final String _source;
	
	public Token(int type, int line, int beginIndex, int endIndex, String source) {
		super(line, beginIndex);
		Checker.checkIndex(endIndex, "line");
		Checker.checkEmpty(source, "source\0");
		if(endIndex <= beginIndex) {
			throw new IllegalArgumentException("invalid beginIndex ("+beginIndex+") and endIndex ("+endIndex+") values");
		}
		_type = type;
		_length = endIndex - beginIndex;
		_source = source;
	}

	public int getType() {
		return _type;
	}

	public int getLength() {
		return _length;
	}
	
	public String getSource() {
		return _source;
	}

	public String getTypeAsString() {
		return _names[_type-1];
	}

	public String getRawValue() {
		return _source.substring(getIndex(), getIndex()+_length);
	}

	public String getUnescapedValue() {
		return _getUnescapedValue(getRawValue());
	}

	public String getValue() {
		if(_type == STRING_CONSTANT || _type == CHAR_CONSTANT) {
			// Unescape String:
			return _getUnescapedValue(_source.substring(getIndex()+1, getIndex()+_length-1));
		}
		else {
			return getRawValue();
		}
	}

	public String toString() {
		return getValue();
	}
	
	private String _getUnescapedValue(String src) {
		final StringBuilder sb = new StringBuilder();
		for(int i=0; i<src.length(); i++) {
			if(src.charAt(i) == '\\') {
				i++;
				// Regular escaped char:
				if(getEscapeChars().indexOf(src.charAt(i)) != -1) {
					char c = src.charAt(i);
					sb.append(c=='n'?'\n' : (c=='r'?'\r':(c=='t'?'\t':(c=='b'?'\b':(c=='f'?'\f':(c=='0'?'\0':'\\'))))));
				}
				// Custom escaped char:
				else {
					sb.append(src.charAt(i));
				}
			}
			else {
				sb.append(src.charAt(i));
			}
		}
		return sb.toString();
	}
}
